from django.db import models
from django.utils.encoding import force_str
from copy import deepcopy


def get_model_field_changes(original_instance, modified_instance, exclude_fields=None):
    """
    通用函数：对比两个模型实例的字段变化

    参数:
        original_instance: 原始实例（修改前）
        modified_instance: 修改后的实例
        exclude_fields: 需要排除的字段列表，默认为['id', 'create_at', 'update_at']

    返回:
        包含字段变化信息的列表，如 ["字段名: 旧值 → 新值"]
    """
    if exclude_fields is None:
        exclude_fields = ['id', 'create_at', 'update_at']  # 默认排除的字段

    changes = []
    model = original_instance.__class__

    # 获取模型所有字段
    for field in model._meta.get_fields():
        # 跳过不需要比较的字段
        if field.name in exclude_fields:
            continue

        # 处理普通字段
        if isinstance(field, models.Field):
            try:
                old_value = getattr(original_instance, field.name)
                new_value = getattr(modified_instance, field.name)

                # 处理外键字段
                if isinstance(field, models.ForeignKey):
                    old_value = old_value.__str__() if old_value else None
                    new_value = new_value.__str__() if new_value else None
                # 处理布尔值
                elif isinstance(field, models.BooleanField):
                    old_value = "是" if old_value else "否"
                    new_value = "是" if new_value else "否"
                # 其他类型转为字符串
                else:
                    old_value = force_str(old_value) if old_value is not None else "空"
                    new_value = force_str(new_value) if new_value is not None else "空"

                # 如果值发生变化，记录下来
                if old_value != new_value:
                    # 获取字段的verbose_name，如果没有则用字段名
                    field_label = field.verbose_name if hasattr(field, 'verbose_name') else field.name
                    changes.append(f"{field_label}: {old_value} → {new_value}")
            except Exception as e:
                # 处理可能的异常（如某些字段无法直接访问）
                continue

        # 可以在这里添加对ManyToMany等其他关系字段的支持

    return changes


def log_model_changes(admin_instance, request, obj, form, change):
    """
    在Admin中记录模型变化的通用函数
    """
    if change and hasattr(obj, '_original_instance'):
        # 获取字段变化
        changes = get_model_field_changes(obj._original_instance, obj)

        if changes:
            # 构建详细的变更信息
            change_message = "修改内容: " + "；".join(changes)

            # 调用Django的日志记录方法
            from django.contrib.admin.models import LogEntry, CHANGE
            from django.contrib.contenttypes.models import ContentType

            LogEntry.objects.create(
                user_id=request.user.id,
                content_type_id=ContentType.objects.get_for_model(obj).pk,
                object_id=obj.pk,
                object_repr=str(obj),
                action_flag=CHANGE,
                change_message=change_message
            )
